<!DOCTYPE HTML>
<!--
	Dimension by HTML5 UP
	html5up.net | @ajlkn
	Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
 <head>
  <title>
   Dimension by HTML5 UP
  </title>
  <!-- <meta charset="utf-8" /> -->
  <!-- <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> -->
  <meta charset="utf-8"/>
  <meta content="width=device-width,initial-scale=1.0" name="viewport"/>
  <link href="../../assets/css/article.css" rel="stylesheet"/>
  <link href="https://cdn.bootcss.com/highlight.js/9.15.8/styles/github.min.css" rel="stylesheet"/>
  <noscript>
   <link href="../../assets/css/noscript.css" rel="stylesheet"/>
  </noscript>
 </head>
 <body>
  <div id="app">
  </div>
  <!-- built files will be auto injected -->
 </body>
 <body class="is-preload">
  <!-- Wrapper -->
  <div id="wrapper">
   <!-- Main -->
   <div id="main">
    <article id="article">
     <h1 id="mybatis37typehandler">
      MyBatis3源码解析(7)TypeHandler注册与获取
     </h1>
     <hr/>
     <p>
      这是我参与2022首次更文挑战的第13天，活动详情查看：
      <a href="https://juejin.cn/post/7052884569032392740">
       2022首次更文挑战
      </a>
     </p>
     <h2 id="_1">
      简介
     </h2>
     <p>
      在上篇文章中，我们介绍了TypeHandler的简单使用和解析了TypeHandler的处理核心，这篇文章中我们接着看到TypeHandler是如注册和获取使用的
     </p>
     <h2 id="_2">
      源码解析
     </h2>
     <h3 id="typehandler">
      TypeHandler注册
     </h3>
     <p>
      typeHandler注册的函数代码如下：
     </p>
     <ul>
      <li>
       根据JavaType放入第一层Map
      </li>
      <li>
       根据jdbcType放入第二层Map
      </li>
     </ul>
     <div class="codehilite">
      <pre><span></span><code>  <span class="n">configuration</span><span class="p">.</span><span class="na">getTypeHandlerRegistry</span><span class="p">().</span><span class="na">register</span><span class="p">(</span><span class="n">String</span><span class="o">[]</span><span class="p">.</span><span class="na">class</span><span class="p">,</span> <span class="n">JdbcType</span><span class="p">.</span><span class="na">VARCHAR</span><span class="p">,</span> <span class="n">StringArrayTypeHandler</span><span class="p">.</span><span class="na">class</span><span class="p">);</span>

  <span class="kd">private</span> <span class="kt">void</span> <span class="nf">register</span><span class="p">(</span><span class="n">Type</span> <span class="n">javaType</span><span class="p">,</span> <span class="n">JdbcType</span> <span class="n">jdbcType</span><span class="p">,</span> <span class="n">TypeHandler</span><span class="o">&lt;?&gt;</span> <span class="n">handler</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">javaType</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">Map</span><span class="o">&lt;</span><span class="n">JdbcType</span><span class="p">,</span> <span class="n">TypeHandler</span><span class="o">&lt;?&gt;&gt;</span> <span class="n">map</span> <span class="o">=</span> <span class="n">typeHandlerMap</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">javaType</span><span class="p">);</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">map</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">||</span> <span class="n">map</span> <span class="o">==</span> <span class="n">NULL_TYPE_HANDLER_MAP</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">map</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o">&lt;&gt;</span><span class="p">();</span>
      <span class="p">}</span>
      <span class="n">map</span><span class="p">.</span><span class="na">put</span><span class="p">(</span><span class="n">jdbcType</span><span class="p">,</span> <span class="n">handler</span><span class="p">);</span>
      <span class="n">typeHandlerMap</span><span class="p">.</span><span class="na">put</span><span class="p">(</span><span class="n">javaType</span><span class="p">,</span> <span class="n">map</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="n">allTypeHandlersMap</span><span class="p">.</span><span class="na">put</span><span class="p">(</span><span class="n">handler</span><span class="p">.</span><span class="na">getClass</span><span class="p">(),</span> <span class="n">handler</span><span class="p">);</span>
  <span class="p">}</span>
</code></pre>
     </div>
     <h3 id="typehandler_1">
      TypeHandler获取
     </h3>
     <p>
      在探索中，我们发现是在Mapper初始化的过程就会去获取TypeHandler了，在示例代码中我们调用了函数：addMapper
     </p>
     <p>
      在该函数中，我们看到了我们熟悉的（前面文章分析过，Sql执行其实就是从Mapper代理类开始的）MapperProxy相关的东西
     </p>
     <div class="codehilite">
      <pre><span></span><code>  <span class="kd">public</span> <span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="nf">addMapper</span><span class="p">(</span><span class="n">Class</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="n">type</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">type</span><span class="p">.</span><span class="na">isInterface</span><span class="p">())</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">hasMapper</span><span class="p">(</span><span class="n">type</span><span class="p">))</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="n">BindingException</span><span class="p">(</span><span class="s">"Type "</span> <span class="o">+</span> <span class="n">type</span> <span class="o">+</span> <span class="s">" is already known to the MapperRegistry."</span><span class="p">);</span>
      <span class="p">}</span>
      <span class="kt">boolean</span> <span class="n">loadCompleted</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
      <span class="k">try</span> <span class="p">{</span>
          <span class="c1">// 生成我们熟悉的Mapper代理类</span>
        <span class="n">knownMappers</span><span class="p">.</span><span class="na">put</span><span class="p">(</span><span class="n">type</span><span class="p">,</span> <span class="k">new</span> <span class="n">MapperProxyFactory</span><span class="o">&lt;&gt;</span><span class="p">(</span><span class="n">type</span><span class="p">));</span>
        <span class="c1">// It's important that the type is added before the parser is run</span>
        <span class="c1">// otherwise the binding may automatically be attempted by the</span>
        <span class="c1">// mapper parser. If the type is already known, it won't try.</span>
        <span class="n">MapperAnnotationBuilder</span> <span class="n">parser</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MapperAnnotationBuilder</span><span class="p">(</span><span class="n">config</span><span class="p">,</span> <span class="n">type</span><span class="p">);</span>
    <span class="c1">// 进行解析</span>
        <span class="n">parser</span><span class="p">.</span><span class="na">parse</span><span class="p">();</span>
        <span class="n">loadCompleted</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
      <span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">loadCompleted</span><span class="p">)</span> <span class="p">{</span>
          <span class="n">knownMappers</span><span class="p">.</span><span class="na">remove</span><span class="p">(</span><span class="n">type</span><span class="p">);</span>
        <span class="p">}</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>
</code></pre>
     </div>
     <p>
      跟踪下面，我们看到SQLSource生成的相关代码，ParameterMapper就是从SQLSource带下去的
     </p>
     <div class="codehilite">
      <pre><span></span><code>  <span class="kt">void</span> <span class="nf">parseStatement</span><span class="p">(</span><span class="n">Method</span> <span class="n">method</span><span class="p">)</span> <span class="p">{</span>
    <span class="p">......</span>
    <span class="n">getAnnotationWrapper</span><span class="p">(</span><span class="n">method</span><span class="p">,</span> <span class="kc">true</span><span class="p">,</span> <span class="n">statementAnnotationTypes</span><span class="p">).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">statementAnnotation</span> <span class="o">-&gt;</span> <span class="p">{</span>
      <span class="kd">final</span> <span class="n">SqlSource</span> <span class="n">sqlSource</span> <span class="o">=</span> <span class="n">buildSqlSource</span><span class="p">(</span><span class="n">statementAnnotation</span><span class="p">.</span><span class="na">getAnnotation</span><span class="p">(),</span> <span class="n">parameterTypeClass</span><span class="p">,</span> <span class="n">languageDriver</span><span class="p">,</span> <span class="n">method</span><span class="p">);</span>
      <span class="p">......</span>
    <span class="p">});</span>
  <span class="p">}</span>

  <span class="kd">public</span> <span class="n">SqlSource</span> <span class="nf">createSqlSource</span><span class="p">(</span><span class="n">Configuration</span> <span class="n">configuration</span><span class="p">,</span> <span class="n">String</span> <span class="n">script</span><span class="p">,</span> <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">parameterType</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// issue #3</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">script</span><span class="p">.</span><span class="na">startsWith</span><span class="p">(</span><span class="s">"&lt;script&gt;"</span><span class="p">))</span> <span class="p">{</span>
      <span class="n">XPathParser</span> <span class="n">parser</span> <span class="o">=</span> <span class="k">new</span> <span class="n">XPathParser</span><span class="p">(</span><span class="n">script</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="n">configuration</span><span class="p">.</span><span class="na">getVariables</span><span class="p">(),</span> <span class="k">new</span> <span class="n">XMLMapperEntityResolver</span><span class="p">());</span>
      <span class="k">return</span> <span class="n">createSqlSource</span><span class="p">(</span><span class="n">configuration</span><span class="p">,</span> <span class="n">parser</span><span class="p">.</span><span class="na">evalNode</span><span class="p">(</span><span class="s">"/script"</span><span class="p">),</span> <span class="n">parameterType</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
      <span class="c1">// issue #127</span>
      <span class="n">script</span> <span class="o">=</span> <span class="n">PropertyParser</span><span class="p">.</span><span class="na">parse</span><span class="p">(</span><span class="n">script</span><span class="p">,</span> <span class="n">configuration</span><span class="p">.</span><span class="na">getVariables</span><span class="p">());</span>
      <span class="n">TextSqlNode</span> <span class="n">textSqlNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">TextSqlNode</span><span class="p">(</span><span class="n">script</span><span class="p">);</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">textSqlNode</span><span class="p">.</span><span class="na">isDynamic</span><span class="p">())</span> <span class="p">{</span>
    <span class="c1">// 这个暂时不理解</span>
        <span class="k">return</span> <span class="k">new</span> <span class="n">DynamicSqlSource</span><span class="p">(</span><span class="n">configuration</span><span class="p">,</span> <span class="n">textSqlNode</span><span class="p">);</span>
      <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="c1">// 目前走的这个</span>
        <span class="k">return</span> <span class="k">new</span> <span class="n">RawSqlSource</span><span class="p">(</span><span class="n">configuration</span><span class="p">,</span> <span class="n">script</span><span class="p">,</span> <span class="n">parameterType</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>

  <span class="kd">public</span> <span class="n">SqlSource</span> <span class="nf">parse</span><span class="p">(</span><span class="n">String</span> <span class="n">originalSql</span><span class="p">,</span> <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">parameterType</span><span class="p">,</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">Object</span><span class="o">&gt;</span> <span class="n">additionalParameters</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">ParameterMappingTokenHandler</span> <span class="n">handler</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ParameterMappingTokenHandler</span><span class="p">(</span><span class="n">configuration</span><span class="p">,</span> <span class="n">parameterType</span><span class="p">,</span> <span class="n">additionalParameters</span><span class="p">);</span>
    <span class="n">GenericTokenParser</span> <span class="n">parser</span> <span class="o">=</span> <span class="k">new</span> <span class="n">GenericTokenParser</span><span class="p">(</span><span class="s">"#{"</span><span class="p">,</span> <span class="s">"}"</span><span class="p">,</span> <span class="n">handler</span><span class="p">);</span>
    <span class="n">String</span> <span class="n">sql</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">configuration</span><span class="p">.</span><span class="na">isShrinkWhitespacesInSql</span><span class="p">())</span> <span class="p">{</span>
      <span class="n">sql</span> <span class="o">=</span> <span class="n">parser</span><span class="p">.</span><span class="na">parse</span><span class="p">(</span><span class="n">removeExtraWhitespaces</span><span class="p">(</span><span class="n">originalSql</span><span class="p">));</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
      <span class="c1">// 走的这个</span>
      <span class="n">sql</span> <span class="o">=</span> <span class="n">parser</span><span class="p">.</span><span class="na">parse</span><span class="p">(</span><span class="n">originalSql</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="k">new</span> <span class="n">StaticSqlSource</span><span class="p">(</span><span class="n">configuration</span><span class="p">,</span> <span class="n">sql</span><span class="p">,</span> <span class="n">handler</span><span class="p">.</span><span class="na">getParameterMappings</span><span class="p">());</span>
  <span class="p">}</span>
</code></pre>
     </div>
     <p>
      下面是对SQL语句进行了解析，最终的效果是遍历了我们示例SQL中的id和name，对其找到对应的TypeHandler
     </p>
     <p>
      细节部分没怎么看到，暂时跳过
     </p>
     <div class="codehilite">
      <pre><span></span><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">GenericTokenParser</span> <span class="p">{</span>
  <span class="kd">public</span> <span class="n">String</span> <span class="nf">parse</span><span class="p">(</span><span class="n">String</span> <span class="n">text</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">text</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">||</span> <span class="n">text</span><span class="p">.</span><span class="na">isEmpty</span><span class="p">())</span> <span class="p">{</span>
      <span class="k">return</span> <span class="s">""</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="c1">// search open token</span>
    <span class="kt">int</span> <span class="n">start</span> <span class="o">=</span> <span class="n">text</span><span class="p">.</span><span class="na">indexOf</span><span class="p">(</span><span class="n">openToken</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">start</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="n">text</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="kt">char</span><span class="o">[]</span> <span class="n">src</span> <span class="o">=</span> <span class="n">text</span><span class="p">.</span><span class="na">toCharArray</span><span class="p">();</span>
    <span class="kt">int</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="kd">final</span> <span class="n">StringBuilder</span> <span class="n">builder</span> <span class="o">=</span> <span class="k">new</span> <span class="n">StringBuilder</span><span class="p">();</span>
    <span class="n">StringBuilder</span> <span class="n">expression</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
    <span class="k">do</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">start</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">src</span><span class="o">[</span><span class="n">start</span> <span class="o">-</span> <span class="mi">1</span><span class="o">]</span> <span class="o">==</span> <span class="sc">'\\'</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// this open token is escaped. remove the backslash and continue.</span>
        <span class="n">builder</span><span class="p">.</span><span class="na">append</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">offset</span><span class="p">,</span> <span class="n">start</span> <span class="o">-</span> <span class="n">offset</span> <span class="o">-</span> <span class="mi">1</span><span class="p">).</span><span class="na">append</span><span class="p">(</span><span class="n">openToken</span><span class="p">);</span>
        <span class="n">offset</span> <span class="o">=</span> <span class="n">start</span> <span class="o">+</span> <span class="n">openToken</span><span class="p">.</span><span class="na">length</span><span class="p">();</span>
      <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="c1">// found open token. let's search close token.</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">expression</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
          <span class="n">expression</span> <span class="o">=</span> <span class="k">new</span> <span class="n">StringBuilder</span><span class="p">();</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
          <span class="n">expression</span><span class="p">.</span><span class="na">setLength</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="n">builder</span><span class="p">.</span><span class="na">append</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">offset</span><span class="p">,</span> <span class="n">start</span> <span class="o">-</span> <span class="n">offset</span><span class="p">);</span>
        <span class="n">offset</span> <span class="o">=</span> <span class="n">start</span> <span class="o">+</span> <span class="n">openToken</span><span class="p">.</span><span class="na">length</span><span class="p">();</span>
        <span class="kt">int</span> <span class="n">end</span> <span class="o">=</span> <span class="n">text</span><span class="p">.</span><span class="na">indexOf</span><span class="p">(</span><span class="n">closeToken</span><span class="p">,</span> <span class="n">offset</span><span class="p">);</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">end</span> <span class="o">&gt;</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">end</span> <span class="o">&gt;</span> <span class="n">offset</span> <span class="o">&amp;&amp;</span> <span class="n">src</span><span class="o">[</span><span class="n">end</span> <span class="o">-</span> <span class="mi">1</span><span class="o">]</span> <span class="o">==</span> <span class="sc">'\\'</span><span class="p">)</span> <span class="p">{</span>
            <span class="c1">// this close token is escaped. remove the backslash and continue.</span>
            <span class="n">expression</span><span class="p">.</span><span class="na">append</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">offset</span><span class="p">,</span> <span class="n">end</span> <span class="o">-</span> <span class="n">offset</span> <span class="o">-</span> <span class="mi">1</span><span class="p">).</span><span class="na">append</span><span class="p">(</span><span class="n">closeToken</span><span class="p">);</span>
            <span class="n">offset</span> <span class="o">=</span> <span class="n">end</span> <span class="o">+</span> <span class="n">closeToken</span><span class="p">.</span><span class="na">length</span><span class="p">();</span>
            <span class="n">end</span> <span class="o">=</span> <span class="n">text</span><span class="p">.</span><span class="na">indexOf</span><span class="p">(</span><span class="n">closeToken</span><span class="p">,</span> <span class="n">offset</span><span class="p">);</span>
          <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="n">expression</span><span class="p">.</span><span class="na">append</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">offset</span><span class="p">,</span> <span class="n">end</span> <span class="o">-</span> <span class="n">offset</span><span class="p">);</span>
            <span class="k">break</span><span class="p">;</span>
          <span class="p">}</span>
        <span class="p">}</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">end</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
          <span class="c1">// close token was not found.</span>
          <span class="n">builder</span><span class="p">.</span><span class="na">append</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">src</span><span class="p">.</span><span class="na">length</span> <span class="o">-</span> <span class="n">start</span><span class="p">);</span>
          <span class="n">offset</span> <span class="o">=</span> <span class="n">src</span><span class="p">.</span><span class="na">length</span><span class="p">;</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
          <span class="n">builder</span><span class="p">.</span><span class="na">append</span><span class="p">(</span><span class="n">handler</span><span class="p">.</span><span class="na">handleToken</span><span class="p">(</span><span class="n">expression</span><span class="p">.</span><span class="na">toString</span><span class="p">()));</span>
          <span class="n">offset</span> <span class="o">=</span> <span class="n">end</span> <span class="o">+</span> <span class="n">closeToken</span><span class="p">.</span><span class="na">length</span><span class="p">();</span>
        <span class="p">}</span>
      <span class="p">}</span>
      <span class="n">start</span> <span class="o">=</span> <span class="n">text</span><span class="p">.</span><span class="na">indexOf</span><span class="p">(</span><span class="n">openToken</span><span class="p">,</span> <span class="n">offset</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">start</span> <span class="o">&gt;</span> <span class="o">-</span><span class="mi">1</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">offset</span> <span class="o">&lt;</span> <span class="n">src</span><span class="p">.</span><span class="na">length</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">builder</span><span class="p">.</span><span class="na">append</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">offset</span><span class="p">,</span> <span class="n">src</span><span class="p">.</span><span class="na">length</span> <span class="o">-</span> <span class="n">offset</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">builder</span><span class="p">.</span><span class="na">toString</span><span class="p">();</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre>
     </div>
     <p>
      下面就是根据对应的JavaType和jdbcType,获取对应的TypeHandler
     </p>
     <div class="codehilite">
      <pre><span></span><code>    <span class="kd">public</span> <span class="n">String</span> <span class="nf">handleToken</span><span class="p">(</span><span class="n">String</span> <span class="n">content</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">parameterMappings</span><span class="p">.</span><span class="na">add</span><span class="p">(</span><span class="n">buildParameterMapping</span><span class="p">(</span><span class="n">content</span><span class="p">));</span>
      <span class="k">return</span> <span class="s">"?"</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// 在其中设置JavaType和jdbcType</span>
    <span class="kd">private</span> <span class="n">ParameterMapping</span> <span class="nf">buildParameterMapping</span><span class="p">(</span><span class="n">String</span> <span class="n">content</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">String</span><span class="o">&gt;</span> <span class="n">propertiesMap</span> <span class="o">=</span> <span class="n">parseParameterMapping</span><span class="p">(</span><span class="n">content</span><span class="p">);</span>
      <span class="n">String</span> <span class="n">property</span> <span class="o">=</span> <span class="n">propertiesMap</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="s">"property"</span><span class="p">);</span>
      <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">propertyType</span><span class="p">;</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">metaParameters</span><span class="p">.</span><span class="na">hasGetter</span><span class="p">(</span><span class="n">property</span><span class="p">))</span> <span class="p">{</span> <span class="c1">// issue #448 get type from additional params</span>
        <span class="n">propertyType</span> <span class="o">=</span> <span class="n">metaParameters</span><span class="p">.</span><span class="na">getGetterType</span><span class="p">(</span><span class="n">property</span><span class="p">);</span>
      <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">typeHandlerRegistry</span><span class="p">.</span><span class="na">hasTypeHandler</span><span class="p">(</span><span class="n">parameterType</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">propertyType</span> <span class="o">=</span> <span class="n">parameterType</span><span class="p">;</span>
      <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">JdbcType</span><span class="p">.</span><span class="na">CURSOR</span><span class="p">.</span><span class="na">name</span><span class="p">().</span><span class="na">equals</span><span class="p">(</span><span class="n">propertiesMap</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="s">"jdbcType"</span><span class="p">)))</span> <span class="p">{</span>
        <span class="n">propertyType</span> <span class="o">=</span> <span class="n">java</span><span class="p">.</span><span class="na">sql</span><span class="p">.</span><span class="na">ResultSet</span><span class="p">.</span><span class="na">class</span><span class="p">;</span>
      <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">property</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">||</span> <span class="n">Map</span><span class="p">.</span><span class="na">class</span><span class="p">.</span><span class="na">isAssignableFrom</span><span class="p">(</span><span class="n">parameterType</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">propertyType</span> <span class="o">=</span> <span class="n">Object</span><span class="p">.</span><span class="na">class</span><span class="p">;</span>
      <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">MetaClass</span> <span class="n">metaClass</span> <span class="o">=</span> <span class="n">MetaClass</span><span class="p">.</span><span class="na">forClass</span><span class="p">(</span><span class="n">parameterType</span><span class="p">,</span> <span class="n">configuration</span><span class="p">.</span><span class="na">getReflectorFactory</span><span class="p">());</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">metaClass</span><span class="p">.</span><span class="na">hasGetter</span><span class="p">(</span><span class="n">property</span><span class="p">))</span> <span class="p">{</span>
          <span class="n">propertyType</span> <span class="o">=</span> <span class="n">metaClass</span><span class="p">.</span><span class="na">getGetterType</span><span class="p">(</span><span class="n">property</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
          <span class="n">propertyType</span> <span class="o">=</span> <span class="n">Object</span><span class="p">.</span><span class="na">class</span><span class="p">;</span>
        <span class="p">}</span>
      <span class="p">}</span>
      <span class="n">ParameterMapping</span><span class="p">.</span><span class="na">Builder</span> <span class="n">builder</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ParameterMapping</span><span class="p">.</span><span class="na">Builder</span><span class="p">(</span><span class="n">configuration</span><span class="p">,</span> <span class="n">property</span><span class="p">,</span> <span class="n">propertyType</span><span class="p">);</span>
      <span class="n">Class</span><span class="o">&lt;?&gt;</span> <span class="n">javaType</span> <span class="o">=</span> <span class="n">propertyType</span><span class="p">;</span>
      <span class="n">String</span> <span class="n">typeHandlerAlias</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
      <span class="k">for</span> <span class="p">(</span><span class="n">Map</span><span class="p">.</span><span class="na">Entry</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">String</span><span class="o">&gt;</span> <span class="n">entry</span> <span class="p">:</span> <span class="n">propertiesMap</span><span class="p">.</span><span class="na">entrySet</span><span class="p">())</span> <span class="p">{</span>
        <span class="n">String</span> <span class="n">name</span> <span class="o">=</span> <span class="n">entry</span><span class="p">.</span><span class="na">getKey</span><span class="p">();</span>
        <span class="n">String</span> <span class="n">value</span> <span class="o">=</span> <span class="n">entry</span><span class="p">.</span><span class="na">getValue</span><span class="p">();</span>
        <span class="k">if</span> <span class="p">(</span><span class="s">"javaType"</span><span class="p">.</span><span class="na">equals</span><span class="p">(</span><span class="n">name</span><span class="p">))</span> <span class="p">{</span>
          <span class="n">javaType</span> <span class="o">=</span> <span class="n">resolveClass</span><span class="p">(</span><span class="n">value</span><span class="p">);</span>
          <span class="n">builder</span><span class="p">.</span><span class="na">javaType</span><span class="p">(</span><span class="n">javaType</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="s">"jdbcType"</span><span class="p">.</span><span class="na">equals</span><span class="p">(</span><span class="n">name</span><span class="p">))</span> <span class="p">{</span>
          <span class="n">builder</span><span class="p">.</span><span class="na">jdbcType</span><span class="p">(</span><span class="n">resolveJdbcType</span><span class="p">(</span><span class="n">value</span><span class="p">));</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="s">"mode"</span><span class="p">.</span><span class="na">equals</span><span class="p">(</span><span class="n">name</span><span class="p">))</span> <span class="p">{</span>
          <span class="n">builder</span><span class="p">.</span><span class="na">mode</span><span class="p">(</span><span class="n">resolveParameterMode</span><span class="p">(</span><span class="n">value</span><span class="p">));</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="s">"numericScale"</span><span class="p">.</span><span class="na">equals</span><span class="p">(</span><span class="n">name</span><span class="p">))</span> <span class="p">{</span>
          <span class="n">builder</span><span class="p">.</span><span class="na">numericScale</span><span class="p">(</span><span class="n">Integer</span><span class="p">.</span><span class="na">valueOf</span><span class="p">(</span><span class="n">value</span><span class="p">));</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="s">"resultMap"</span><span class="p">.</span><span class="na">equals</span><span class="p">(</span><span class="n">name</span><span class="p">))</span> <span class="p">{</span>
          <span class="n">builder</span><span class="p">.</span><span class="na">resultMapId</span><span class="p">(</span><span class="n">value</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="s">"typeHandler"</span><span class="p">.</span><span class="na">equals</span><span class="p">(</span><span class="n">name</span><span class="p">))</span> <span class="p">{</span>
          <span class="n">typeHandlerAlias</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="s">"jdbcTypeName"</span><span class="p">.</span><span class="na">equals</span><span class="p">(</span><span class="n">name</span><span class="p">))</span> <span class="p">{</span>
          <span class="n">builder</span><span class="p">.</span><span class="na">jdbcTypeName</span><span class="p">(</span><span class="n">value</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="s">"property"</span><span class="p">.</span><span class="na">equals</span><span class="p">(</span><span class="n">name</span><span class="p">))</span> <span class="p">{</span>
          <span class="c1">// Do Nothing</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="s">"expression"</span><span class="p">.</span><span class="na">equals</span><span class="p">(</span><span class="n">name</span><span class="p">))</span> <span class="p">{</span>
          <span class="k">throw</span> <span class="k">new</span> <span class="n">BuilderException</span><span class="p">(</span><span class="s">"Expression based parameters are not supported yet"</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
          <span class="k">throw</span> <span class="k">new</span> <span class="n">BuilderException</span><span class="p">(</span><span class="s">"An invalid property '"</span> <span class="o">+</span> <span class="n">name</span> <span class="o">+</span> <span class="s">"' was found in mapping #{"</span> <span class="o">+</span> <span class="n">content</span> <span class="o">+</span> <span class="s">"}.  Valid properties are "</span> <span class="o">+</span> <span class="n">PARAMETER_PROPERTIES</span><span class="p">);</span>
        <span class="p">}</span>
      <span class="p">}</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">typeHandlerAlias</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">builder</span><span class="p">.</span><span class="na">typeHandler</span><span class="p">(</span><span class="n">resolveTypeHandler</span><span class="p">(</span><span class="n">javaType</span><span class="p">,</span> <span class="n">typeHandlerAlias</span><span class="p">));</span>
      <span class="p">}</span>
      <span class="k">return</span> <span class="n">builder</span><span class="p">.</span><span class="na">build</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="kd">public</span> <span class="n">ParameterMapping</span> <span class="nf">build</span><span class="p">()</span> <span class="p">{</span>
      <span class="n">resolveTypeHandler</span><span class="p">();</span>
      <span class="n">validate</span><span class="p">();</span>
      <span class="k">return</span> <span class="n">parameterMapping</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kd">private</span> <span class="kt">void</span> <span class="nf">resolveTypeHandler</span><span class="p">()</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">parameterMapping</span><span class="p">.</span><span class="na">typeHandler</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">&amp;&amp;</span> <span class="n">parameterMapping</span><span class="p">.</span><span class="na">javaType</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">Configuration</span> <span class="n">configuration</span> <span class="o">=</span> <span class="n">parameterMapping</span><span class="p">.</span><span class="na">configuration</span><span class="p">;</span>
        <span class="n">TypeHandlerRegistry</span> <span class="n">typeHandlerRegistry</span> <span class="o">=</span> <span class="n">configuration</span><span class="p">.</span><span class="na">getTypeHandlerRegistry</span><span class="p">();</span>
    <span class="c1">// 从Map中获取对应的TypeHandler，以javaType和jdbcType为标识</span>
        <span class="n">parameterMapping</span><span class="p">.</span><span class="na">typeHandler</span> <span class="o">=</span> <span class="n">typeHandlerRegistry</span><span class="p">.</span><span class="na">getTypeHandler</span><span class="p">(</span><span class="n">parameterMapping</span><span class="p">.</span><span class="na">javaType</span><span class="p">,</span> <span class="n">parameterMapping</span><span class="p">.</span><span class="na">jdbcType</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">}</span>

  <span class="kd">private</span> <span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="n">TypeHandler</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="nf">getTypeHandler</span><span class="p">(</span><span class="n">Type</span> <span class="n">type</span><span class="p">,</span> <span class="n">JdbcType</span> <span class="n">jdbcType</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">ParamMap</span><span class="p">.</span><span class="na">class</span><span class="p">.</span><span class="na">equals</span><span class="p">(</span><span class="n">type</span><span class="p">))</span> <span class="p">{</span>
      <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="c1">// 根据javaType获取Map</span>
    <span class="n">Map</span><span class="o">&lt;</span><span class="n">JdbcType</span><span class="p">,</span> <span class="n">TypeHandler</span><span class="o">&lt;?&gt;&gt;</span> <span class="n">jdbcHandlerMap</span> <span class="o">=</span> <span class="n">getJdbcHandlerMap</span><span class="p">(</span><span class="n">type</span><span class="p">);</span>
    <span class="n">TypeHandler</span><span class="o">&lt;?&gt;</span> <span class="n">handler</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">jdbcHandlerMap</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
      <span class="c1">// 根据jdbcType获取</span>
      <span class="n">handler</span> <span class="o">=</span> <span class="n">jdbcHandlerMap</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">jdbcType</span><span class="p">);</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">handler</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">handler</span> <span class="o">=</span> <span class="n">jdbcHandlerMap</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span>
      <span class="p">}</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">handler</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// #591</span>
        <span class="n">handler</span> <span class="o">=</span> <span class="n">pickSoleHandler</span><span class="p">(</span><span class="n">jdbcHandlerMap</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">}</span>
    <span class="c1">// type drives generics here</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">TypeHandler</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">)</span> <span class="n">handler</span><span class="p">;</span>
  <span class="p">}</span>
</code></pre>
     </div>
     <h2 id="_3">
      总结
     </h2>
     <p>
      在本篇文章中，我们初步探索了Mapper初始化的一部分，着重解析了TypeHandler相关的注册和MapperProxy生成时TypeHandler对应的获取
     </p>
     <p>
      核心流程如下：
     </p>
     <ul>
      <li>
       1.注册TypeHandler：放入Map中
      </li>
      <li>
       2.MapperProxy生成，字段的TypeHandler是在SQLSource中，生成SQLSource
      </li>
      <li>
       3.解析SQL语句，得到对应参数和返回字段的TypeHandler：这部分没细研究，但后面如果遇到问题，可以回来参考参考
      </li>
      <li>
       4.根据JavaType和jdbcType得到对应的TypeHandler
      </li>
     </ul>
     <p>
      这部分还有很多的细节没来得及去细看，但如果遇到问题，还是能提供方向性的指导
     </p>
    </article>
   </div>
   <!-- Footer -->
   <footer id="footer">
    <p class="copyright">
     © Untitled. Design:
     <a href="https://html5up.net">
      HTML5 UP
     </a>
     .
    </p>
   </footer>
  </div>
  <!-- BG -->
  <div id="bg">
  </div>
  <!-- Scripts -->
  <script src="../assets/js/jquery.min.js">
  </script>
  <script src="../assets/js/browser.min.js">
  </script>
  <script src="../assets/js/breakpoints.min.js">
  </script>
  <script src="../assets/js/util.js">
  </script>
  <script src="../assets/js/main.js">
  </script>
 </body>
</html>
